package com.rtc.call.core

import android.app.Activity
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.nfc.NdefMessage
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.Ndef
import android.os.Build
import android.os.Parcelable
import android.util.Log
import java.io.IOException
import java.util.concurrent.atomic.AtomicBoolean

/**
 * NFC result sealed class for handling different NFC states
 */
sealed class NfcResult {
    object NfcOn : NfcResult()
    object NfcOff : NfcResult()
}

/**
 * Manages NFC detection and actions
 * Handles "NFC检测" (NFC Detection) step in the flow diagram
 */
class NfcManager(
    private val context: Context,
    private val configManager: ConfigManager
) {
    private val TAG = "NfcManager"
    
    private var nfcAdapter: NfcAdapter? = null
    private var nfcDetectionEnabled = AtomicBoolean(false)
    private var nfcCallback: ((NfcResult) -> Unit)? = null
    
    // Flag to track if an NFC tag is currently attached
    private var isNfcTagAttached = AtomicBoolean(false)
    
    /**
     * Set the NFC adapter
     */
    fun setNfcAdapter(adapter: NfcAdapter?) {
        this.nfcAdapter = adapter
    }
    
    /**
     * Check if NFC is available on the device
     */
    fun isNfcAvailable(): Boolean {
        return nfcAdapter != null
    }
    
    /**
     * Check if NFC is enabled on the device
     */
    fun isNfcEnabled(): Boolean {
        return nfcAdapter?.isEnabled == true
    }
    
    /**
     * Start NFC detection
     * This handles the "持续检测" (Continuous Detection) step in the flow diagram
     */
    fun startNfcDetection(callback: (NfcResult) -> Unit) {
        if (!isNfcAvailable() || !isNfcEnabled()) {
            Log.e(TAG, "NFC is not available or not enabled")
            return
        }
        
        this.nfcCallback = callback
        this.nfcDetectionEnabled.set(true)
        
        Log.d(TAG, "NFC detection started")
    }
    
    /**
     * Stop NFC detection
     */
    fun stopNfcDetection() {
        this.nfcDetectionEnabled.set(false)
        this.nfcCallback = null
        Log.d(TAG, "NFC detection stopped")
    }
    
    /**
     * Enable foreground dispatch for NFC detection in an activity
     */
    fun enableForegroundDispatch(activity: Activity) {
        if (!isNfcAvailable() || !isNfcEnabled() || !nfcDetectionEnabled.get()) {
            return
        }
        
        try {
            val intent = Intent(activity, activity.javaClass).apply {
                addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
            }
            
            val pendingIntentFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
            } else {
                PendingIntent.FLAG_UPDATE_CURRENT
            }
            
            val pendingIntent = PendingIntent.getActivity(
                activity,
                0,
                intent,
                pendingIntentFlags
            )
            
            val intentFilters = arrayOf(
                IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply {
                    addDataType("*/*")
                },
                IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED),
                IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
            )
            
            nfcAdapter?.enableForegroundDispatch(
                activity,
                pendingIntent,
                intentFilters,
                null
            )
            
            Log.d(TAG, "NFC foreground dispatch enabled")
        } catch (e: Exception) {
            Log.e(TAG, "Error enabling NFC foreground dispatch", e)
        }
    }
    
    /**
     * Disable foreground dispatch
     */
    fun disableForegroundDispatch(activity: Activity) {
        if (!isNfcAvailable() || !isNfcEnabled()) {
            return
        }
        
        try {
            nfcAdapter?.disableForegroundDispatch(activity)
            Log.d(TAG, "NFC foreground dispatch disabled")
        } catch (e: Exception) {
            Log.e(TAG, "Error disabling NFC foreground dispatch", e)
        }
    }
    
    /**
     * Process NFC intent
     * This handles the detection of when an NFC tag is placed or removed
     */
    fun processNfcIntent(intent: Intent) {
        if (!nfcDetectionEnabled.get() || nfcCallback == null) {
            return
        }
        
        val action = intent.action
        
        when (action) {
            NfcAdapter.ACTION_TAG_DISCOVERED,
            NfcAdapter.ACTION_TECH_DISCOVERED,
            NfcAdapter.ACTION_NDEF_DISCOVERED -> {
                // NFC tag was detected
                val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
                
                if (tag != null) {
                    // NFC贴上 - NFC tag was attached
                    if (!isNfcTagAttached.get()) {
                        isNfcTagAttached.set(true)
                        handleNfcAttached(intent)
                    }
                }
            }
        }
    }
    
    /**
     * Simulate NFC tag removed
     * This is used for testing or for cases where the tag removal event is not automatically detected
     */
    fun simulateNfcTagRemoved() {
        if (isNfcTagAttached.get()) {
            isNfcTagAttached.set(false)
            handleNfcDetached()
        }
    }
    
    /**
     * Handle NFC tag attached event
     * This is for "NFC贴上" (NFC attached) step in the flow diagram
     */
    private fun handleNfcAttached(intent: Intent) {
        // Read NDEF message if available
        val rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
        if (rawMessages != null) {
            val messages = rawMessages.map { it as NdefMessage }
            for (message in messages) {
                // Process NDEF message if needed
                val records = message.records
                // Read record payload if needed
            }
        }
        
        // Notify callback
        nfcCallback?.invoke(NfcResult.NfcOn)
        Log.d(TAG, "NFC tag attached")
    }
    
    /**
     * Handle NFC tag detached event
     * This is for "NFC拿开" (NFC removed) step in the flow diagram 
     */
    private fun handleNfcDetached() {
        // Notify callback
        nfcCallback?.invoke(NfcResult.NfcOff)
        Log.d(TAG, "NFC tag detached")
    }
    
    /**
     * Read NFC tag
     */
    fun readNfcTag(tag: Tag): String? {
        val ndef = Ndef.get(tag) ?: return null
        
        try {
            ndef.connect()
            
            val ndefMessage = ndef.ndefMessage ?: return null
            val records = ndefMessage.records
            
            if (records.isNotEmpty()) {
                val record = records[0]
                val payload = record.payload
                
                // Skip language code (first byte) for Text records
                val textData = String(payload, 1, payload.size - 1, Charsets.UTF_8)
                return textData
            }
        } catch (e: IOException) {
            Log.e(TAG, "Error reading NFC tag", e)
        } finally {
            try {
                ndef.close()
            } catch (e: IOException) {
                Log.e(TAG, "Error closing NFC connection", e)
            }
        }
        
        return null
    }
} 